﻿#include <iostream>
#include <string>
#include <sstream>
#include <map>
#include <initializer_list>
using namespace std;
/* 对象结构型模式
1.意图
运用共享技术有效地支持大量细粒度的对象
2.适用性
Flyweight模式的有效性很大程度上取决于如何使用它以及在何处使用它。当以下情况都成立时使用Flyweight模式：
a.一个应用程序使用了大量的对象
b.完全由于使用大量的对象，造成很大地存储开销
c.对象的大多数状态都可变为外部状态
d.如果删除对象的外部状态，那么可以用相对较少的共享对象取代很多组对象
e.应用程序不依赖于对象标识。由于Flyweight对象可以共享，对于概念上明显有别的对象，标识测试将返回真值
*/
//事物属性抽象，分为两部分
class SharedState
{
public:
	SharedState(const string brand,const string model,const string color):brand(brand),model(model),color(color){}
	const string GetBrand()const { return brand; }
	const string GetModel() const { return model; }
	const string GetColor() const{ return color; }
	friend ostream& operator<<(ostream& out, SharedState ss)
	{
		return out << "[" << ss.brand << "," << ss.model << "," << ss.color << "]";
	}
protected:
	string brand;
	string model;
	string color;
};
class UniqueState
{
private:
	string owner;
	string plates;
public:
	UniqueState(const string owner,const string plates):owner(owner),plates(plates){}
	const string GetOwner()const { return owner; }
	const string GetPlates()const { return plates; }
	friend ostream& operator<<(ostream& out,const UniqueState ss)
	{
		return out << "[" << ss.owner << "," << ss.plates << "]";
	}
};
class Flyweight
{
private:
	SharedState* sharedstate;
public:
	//拷贝构造，不需要创建新对象
	Flyweight(const SharedState* sharedstate):sharedstate(new SharedState(*sharedstate))
	{

	}
	Flyweight(const Flyweight& other):sharedstate(new SharedState(*other.sharedstate))
	{
	
	}
	SharedState* GetShardState()const { return sharedstate; }
	void Show(const UniqueState& uniquestate)const
	{
		cout << "共享数据：" << *sharedstate << endl;
		cout << "专有数据：" << uniquestate << endl;
	}
};
class FlyweightFactory
{
private:
	map<string, Flyweight> flyweight;
	string GetKey(const SharedState& ss) const
	{
		return ss.GetBrand() + "_" + ss.GetModel() + "_" + ss.GetColor();
	}
public:
	FlyweightFactory(initializer_list<SharedState> sharedstate)
	{
		for (auto v : sharedstate)
		{
			this->flyweight.insert(make_pair<string,Flyweight>(this->GetKey(v), Flyweight(&v)));
		}
	}
	Flyweight GetFlyweight(const SharedState& sharedstate)
	{
		string key = this->GetKey(sharedstate);
		if (this->flyweight.find(key) == this->flyweight.end())
		{
			cout<<"车库未找到这个款式..."<<endl;
			this->flyweight.insert(make_pair(key, Flyweight(&sharedstate)));
			cout << "第一次入库成功" << endl;
		}
		else
		{
			cout << "车库找到这个款式..." << endl;
		}
		return this->flyweight.at(key);
	}
	void ListFlyweights() const
	{
		int count = this->flyweight.size();
		cout << "车库总信息：" << endl;
		for (auto pair : this->flyweight)
		{
			cout << pair.first << "\n";
		}
	}
};

void AddCar(FlyweightFactory& ff,const string& plates,const string& owner,const string& brand,const string& model,const string& color)
{
	cout << "车型匹配结果：" << endl;
	auto flyweight = ff.GetFlyweight({ brand,model,color });
	flyweight.Show({ owner,plates });
}
/*
int main()
{
	FlyweightFactory* f = new FlyweightFactory(
		{
			{"雪佛兰","2020","pink"},
			{"奔驰","C43","black"},
			{"奔驰","C63","red"},
			{"宝马","M6","red"},
			{"宝马","X7","white"},
		}
		);
	f->ListFlyweights();
	cout << endl;
	AddCar(*f, "DK88888", "顽石", "宝马", "M6", "red");
	AddCar(*f, "DK66666", "里奇", "宝马", "X7", "red");
	cout << endl;
	f->ListFlyweights();
	delete f;

	return 0;
}
*/